#pragma once

namespace utility {
template <class T>
class UniquePtr {
public:
    UniquePtr() : _data(nullptr) {}

    UniquePtr(T* data) : _data(data) {}

    UniquePtr(const UniquePtr& other) = delete;

    UniquePtr(UniquePtr<T>&& other) noexcept : _data(other.release()) {}

    ~UniquePtr() {
        if (_data != nullptr) {
            delete _data;
            _data = nullptr;
        }
    }

    T* get() const { return _data; }

    T* release() {
        auto data = _data;
        _data = nullptr;
        return data;
    }

    void reset(T* data = nullptr) {
        if (_data != data) {
            delete _data;
            _data = data;
        }
    }

    void swap(UniquePtr<T>& other) {
        auto data = other._data;
        other._data = _data;
        _data = data;
    }

    T* operator->() const { return _data; }

    T& operator*() const { return *_data; }

    T& operator[](int i) const {
        return _data[i];  // 返回数组对象的下标
    }

    explicit operator bool() const noexcept { return _data != nullptr; }

    UniquePtr& operator=(const UniquePtr<T>& other) = delete;
    UniquePtr& operator=(const UniquePtr<T>&& other) {
        if (this == &other) {
            return *this;
        }
        reset(other.release());
        return *this;
    }

private:
    T* _data;
};
};  // namespace utility